using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Xml.Serialization;

namespace Nizm0.QOT.Library.Objects
{
    [Serializable]
    public class DataBase : Objects.ISettingsObjects, IXmlSerializable
    {
        private string _name;

        private int _treelevel = 1;
        private bool _checked = false;
        private object _parent;

        private List<Table> _tables = new List<Table>();
        private List<ProcedureFromDatabase> _procedures = new List<ProcedureFromDatabase>();

        #region Propertiess
        public string DataBaseName
        {
            get { return _name; }
            set { _name = value; }
        }
        public object Parent
        {
            get { return _parent; }
            set { _parent = value; }
        }
        public List<Table> Tables
        {
            get { return _tables; }
            set { _tables = value; }
        }
        public List<ProcedureFromDatabase> Procedures
        {
            get { return _procedures; }
            set { _procedures = value; }
        }
        #endregion

        #region Objects.ISettingsObjects Members

        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }

        public int Treelevel
        {
            get
            {
                return _treelevel;
            }
        }

        public bool Checked
        {
            get
            {
                return _checked;
            }
            set
            {
                _checked = value;
            }
        }

        #endregion

        #region Constructors
        public DataBase()
        { _name = "Null"; }
        public DataBase(string Name, List<Table> tables, List<ProcedureFromDatabase> procedures)
        {
            _name = Name;
            _tables = tables;
            _procedures = procedures;
        }
        public DataBase(string Name, List<Table> tables)
        {
            _name = Name;
            _tables = tables;
        }

        public DataBase(string Name)
        {
            _name = Name;
        }
        #endregion

        //IMPORTAND update to full marge of procedure, table, database and servers
        public void MargeTables(List<Table> tables)
        {
            foreach (Table tmpdatable in tables)
            {
                if (_tables.Exists(t => t.Name == tmpdatable.Name))
                {
                    if (_tables.Find(t => t.Name == tmpdatable.Name).Checked || tmpdatable.Checked) _tables.Find(t => t.Name == tmpdatable.Name).Checked = true; else _tables.Find(t => t.Name == tmpdatable.Name).Checked = false;
                    //_tables[tmpdatable.Key] = tmpdatable.Value;
                }
                else
                {
                    _tables.Add(tmpdatable);
                }
            }

        }

        /// <summary>
        /// please do not use it
        /// </summary>
        /// <param name="databases"></param>
        public void MargeProcedures(List<ProcedureFromDatabase> procedures)
        {
            foreach (ProcedureFromDatabase tmpprocedure in procedures)
            {
                if (_procedures.Exists(p => p.Name == tmpprocedure.Name))
                {
                    if (_procedures.Find(p => p.Name == tmpprocedure.Name).Checked || tmpprocedure.Checked)
                        _procedures.Find(p => p.Name == tmpprocedure.Name).Checked = true;
                    else
                        _procedures.Find(p => p.Name == tmpprocedure.Name).Checked = false;
                    //_procedures[tmpprocedure.Key] = tmpprocedure.Value;
                }
                else
                {
                    _procedures.Add((ProcedureFromDatabase)tmpprocedure);
                }
            }

        }

        public void Marge(DataBase database)
        {
            if (_checked || database.Checked)
                _checked = true;
            else
                _checked = false;
            foreach (Table tmpdatable in database._tables)
            {
                if (_tables.Exists(t => t.Name == tmpdatable.Name))
                {
                    _tables.Find(t => t.Name == tmpdatable.Name).Marge(tmpdatable);
                }
                else
                {
                    _tables.Add(tmpdatable);
                }
            }
            foreach (ProcedureFromDatabase tmpprocedure in database._procedures)
            {
                if (_procedures.Exists(p => p.Name == tmpprocedure.Name))
                {
                    _procedures.Find(p => p.Name == tmpprocedure.Name).Marge(tmpprocedure);
                }
                else
                {
                    _procedures.Add(tmpprocedure);
                }
            }
        }

        public override string ToString()
        {
            return Name;
        }

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            throw new NotImplementedException();
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            _name = reader.GetAttribute("Name");
            Boolean.TryParse(reader.GetAttribute("Checked"), out _checked);

            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            doc.LoadXml(reader.ReadInnerXml());

            foreach (System.Xml.XmlNode node in doc.ChildNodes)
            {
                System.Xml.XmlReader r = new System.Xml.XmlNodeReader(node);

                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Table));//Type.GetType(className));
                var obj = (Table)Convert.ChangeType(serializer.Deserialize(r), typeof(Table));//Type.GetType(className));
                obj.Parent = this;
                _tables.Add(obj);
            }
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteAttributeString("Name", _name);
            writer.WriteAttributeString("Checked", _checked.ToString());
            foreach (Table tab in _tables)
            {
                if (tab.Checked)
                {
                    var nsSerializer = new XmlSerializerNamespaces();
                    nsSerializer.Add("", "");
                    System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(tab.GetType(), "");
                    xmlSerializer.Serialize(writer, tab, nsSerializer);
                }
            }
        }
    }
}
